package org.swift.mashup.engine.deployment.mcr;

import org.apache.axiom.om.OMElement;
import org.apache.axiom.soap.SOAPBody;
import org.apache.axis2.context.MessageContext;
import org.swift.mashup.engine.deployment.MessageContextReader;

import java.util.*;

public class BodyMessageContextReader implements MessageContextReader {
	private static BodyMessageContextReader instance = null;

	public static BodyMessageContextReader getInstance() {
		if (instance == null) {
			instance = new BodyMessageContextReader();
		}
		return instance;
	}

	private BodyMessageContextReader() {
	}

	@Override
	public Map<String, Object> createParameterMap(MessageContext context) {
		Map<String,Object> paramMap = new HashMap<String,Object>();
		SOAPBody body = context.getEnvelope().getBody();

		if ( body != null ) {
			addElementsToMap(body.getFirstElement().getChildElements(), paramMap);
		}

		return paramMap;
	}

	private void addElementsToMap(Iterator iterator, Map<String, Object> map) {
		while (iterator.hasNext()) {
			OMElement child = (OMElement) iterator.next();

			String key = child.getLocalName();
			Object value = child.getText();

			if ( hasXMLContent(child) ) {
				try {
					value = org.swift.commons.xml.OMUtils.toDOM(child);
				}
				catch (Exception e) {
					e.printStackTrace();
				}
			}

			if( map.containsKey(key) ) {
				Object oldVal = map.get(key);

				if ( oldVal instanceof String ) {
					value = oldVal + "," + String.valueOf(value);
				}
				else if ( oldVal instanceof Collection) {
					((Collection) oldVal).add(value);
					value = oldVal;
				}
				else {
					ArrayList list = new ArrayList();
					list.add(oldVal);
					list.add(value);
					value = list;
				}
			}

			map.put(key, value);
		}
	}

    private boolean hasXMLContent(OMElement element) {
        if ( element.getFirstElement() != null ) {
            return true;
        }

        Iterator attributes = element.getAllAttributes();
        if ( attributes != null && attributes.hasNext() ) {
            return true;
        }

        return false;
    }
}
